package nc.impl.hrppl.pjapplication.pjappl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import nc.impl.pubapp.pattern.data.vo.VOQuery;
import nc.itf.hrpbm.sjxm.sjxmh.ISjxmHVOService;
import nc.itf.hrppl.pjapplication.IUapbdFourProjectService;
import nc.pubitf.para.SysInitQuery;
import nc.vo.hrppl.pjapplication.*;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.org.DeptVO;
import nc.vo.pmpub.eps.EpsVO;
import nc.vo.sjxm.sjxm.AggSjxmVO;
import nc.vo.sjxm.sjxm.SjxmBVO;
import nc.vo.sjxm.sjxm.SjxmHVO;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.hrppl.pjapplication.ace.bp.rule.AcePjapplicationDataRule;
import nc.bs.hrppl.pjapplication.ace.bp.rule.VersionProcessRule;
import nc.bs.hrppl.pjapplication.plugin.bpplugin.PjapplicationPluginPoint;
import nc.bs.pf.pub.PfDataCache;
import nc.codeplatform.framework.service.ServiceSupport;
import nc.impl.pub.util.db.InSqlManager;
import nc.impl.pubapp.pattern.data.bill.BillQuery;
import nc.impl.pubapp.pattern.data.bill.template.InsertBPTemplate;
import nc.impl.pubapp.pattern.rule.ICompareRule;
import nc.itf.hrppl.pjapplication.pjappl.IPJApplHVOService;
import nc.itf.hrppl.pub.NbcrCodeTool;
import nc.itf.pmpub.prv.IProject;
import nc.pub.billcode.vo.BillCodeContext;
import nc.vo.hrppl.hrppjplnum.PjlibcategoryEnumerate;
import nc.vo.hrppl.hrppjplnum.PjstatusEnumerate;
import nc.vo.pmpub.project.ProjectBillVO;
import nc.vo.pmpub.project.ProjectBodyVO;
import nc.vo.pmpub.project.ProjectHeadVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.ISuperVO;
import nc.vo.pub.SuperVO;
import nc.vo.pub.VOStatus;
import nc.vo.pub.billtype.BilltypeVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pub.pf.BillStatusEnum;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.model.entity.bill.AbstractBill;
import nccloud.putitf.riart.billtype.IBilltypeService;

public class PJApplHVOServiceImpl extends ServiceSupport implements IPJApplHVOService {

    @Override
    public AggPjapplVO[] listAggPjapplVOByPk(String... pks) throws BusinessException {
        return listAggPjapplVOByPk(false, pks);
    }

    @Override
    public AggPjapplVO[] listAggPjapplVOByPk(boolean blazyLoad, String... pks) throws BusinessException {
        return dao.listByPksWithOrder(AggPjapplVO.class, pks, blazyLoad);
    }

    @Override
    public AggPjapplVO findAggPjapplVOByPk(String pk) throws BusinessException {
        return dao.findByPk(AggPjapplVO.class, pk, false);
    }

    @Override
    public AggPjapplVO[] listAggPjapplVOByCondition(String condition) throws BusinessException {
        return listAggPjapplVOByCondition(condition, new String[]{PJApplHVO.PK_PJAPPL});
    }

    @Override
    public AggPjapplVO[] listAggPjapplVOByCondition(String condition, String[] orderPath) throws BusinessException {
        return dao.listByCondition(AggPjapplVO.class, condition, false, false, orderPath);
    }

    @Override
    public PJApplHVO[] listPJApplHVOByPk(String... pks) throws BusinessException {
        return dao.listByPk(PJApplHVO.class, pks, true);
    }

    @Override
    public PJApplHVO findPJApplHVOByPk(String pk) throws BusinessException {
        return dao.findByPk(PJApplHVO.class, pk, true);
    }

    @Override
    public PJApplHVO[] listPJApplHVOByCondition(String condition) throws BusinessException {
        return listPJApplHVOByCondition(condition, new String[]{PJApplHVO.PK_PJAPPL});
    }

    @Override
    public PJApplHVO[] listPJApplHVOByCondition(String condition, String[] orderPath) throws BusinessException {
        return dao.listByCondition(PJApplHVO.class, condition, false, false, orderPath);
    }

    @Override
    public String[] listPJApplHVOPkByCond(String condition) throws BusinessException {
        return listPJApplHVOPkByCond(condition, new String[]{PJApplHVO.APPLICATIONDATE});
    }

    @Override
    public String[] listPJApplHVOPkByCond(String condition, String[] orderPath) throws BusinessException {
        if (StringUtils.isEmpty(condition)) {
            condition = " 1 = 1 ";
        }
        StringBuilder sql = new StringBuilder();
        sql.append(" select pk_pjappl from ").append(PJApplHVO.getDefaultTableName());
        sql.append(" where ").append(condition);
        if (ArrayUtils.isNotEmpty(orderPath)) {
            sql.append(" order by ").append(StringUtils.join(orderPath, ", ")).append(" desc ");
        }
        return (String[]) dao.getBaseDAO().executeQuery(sql.toString(), (rs) -> {
            List<String> pks = new ArrayList<>();
            while (rs.next()) {
                pks.add(rs.getString(1));
            }
            return pks.toArray(new String[0]);
        });
    }

    @Override
    public void initDefaultData(PJApplHVO vo) {
        if (vo.getAttributeValue("pk_group") == null) {
            vo.setAttributeValue("pk_group", InvocationInfoProxy.getInstance().getGroupId());
        }
        if (vo.getAttributeValue("billmaker") == null) {
            vo.setAttributeValue("billmaker", InvocationInfoProxy.getInstance().getUserId());
        }
        if (vo.getAttributeValue("maketime") == null) {
            vo.setAttributeValue("maketime", new UFDateTime(InvocationInfoProxy.getInstance().getBizDateTime()));
        }
        UFDate newStartingdate = new UFDate(InvocationInfoProxy.getInstance().getBizDateTime());
        if (vo.getAttributeValue("dbilldate") == null) {
            vo.setAttributeValue("dbilldate", newStartingdate);
        }
        if (vo.getAttributeValue("billtype") == null) {
            vo.setAttributeValue("billtype", "PL01");
        }
        if (vo.getAttributeValue("approvestatus") == null) {
            vo.setAttributeValue("approvestatus", BillStatusEnum.FREE.toIntValue());
        }

        //代码已经迁移至其他类中
//		// 申请人
//		String pk_psndoc = null;
//		try {
//			pk_psndoc = NCLocator.getInstance().lookup(IUserPubService.class)
//					.queryPsndocByUserid(InvocationInfoProxy.getInstance().getUserId());
//		} catch (BusinessException e) {
//			Logger.error_null(e.getMessage(), e);
//		}
//		
//		try {
//			SQLParameter paramSQLParameter = new SQLParameter();
//			paramSQLParameter.addParam(pk_psndoc);
//			paramSQLParameter.addParam(vo.getPk_org());
//			String matchv = (String) dao.getBaseDAO().executeQuery("select pk_psndoc from bd_psndoc where pk_psndoc=? and pk_org=? and dr = 0 and enablestate = 2", paramSQLParameter, new ColumnProcessor());
//			pk_psndoc=matchv;
//		} catch (BusinessException e) {
//			nc.bs.logging.Logger.error(e.getMessage());
//		}
//vo.setAttributeValue("applicant", pk_psndoc);

        // 申请年度
        if (StringUtils.isBlank(vo.getApplyyear())) {
            vo.setApplyyear(vo.getDbilldate().getYear() + "");
        }

        // 项目状态
        vo.setPjstatus(Integer.valueOf(1));

        // 所属项目库
        vo.setPjlibcategory(Integer.valueOf(1));

        // 版本号
        vo.setVersionno(UFDouble.ONE_DBL);

        //最新版本
        vo.setIslastversion(UFBoolean.TRUE);

        // 是否集团
        if (vo.getIsgroup() == null) {
//			if( vo.getIsgroup() ==null ||  (!vo.getIsgroup().booleanValue()) ) {
            vo.setIsgroup(UFBoolean.FALSE);
        }

        //开始日期
        if (vo.getStartingdate() == null) {
            vo.setStartingdate(newStartingdate);
        }

        //申请日期
        if (vo.getApplicationdate() == null) {
            vo.setApplicationdate(newStartingdate);
        }

        //默认人民币种
        vo.setCurrencytype(nc.vo.pmpub.uap.currency.CurrencyUtils.getGlobalDefaultCurrencyPK());

    }

    @Override
    public AggPjapplVO preAddAggPjapplVO(AggPjapplVO vo, Map<String, Object> userJson) throws BusinessException {

        getMainVO(vo).setStatus(VOStatus.NEW);
        initDefaultData((PJApplHVO) getMainVO(vo));

        // 下面这段要判断是否是树表界面插件
        Map<String, String> data = userJson != null && userJson.get("data") != null
                ? (Map<String, String>) userJson.get("data")
                : null;
        if (data != null && data.size() > 0) {
            String parentKey = data.get("parentKey");
            String parentPk = data.get("parentPk");
            getMainVO(vo).setAttributeValue(parentKey, parentPk);
        }

        String transtype = vo.getParentVO().getTranstype();
        String transtypepk = vo.getParentVO().getTranstypepk();
        if (transtype == null) {
            BilltypeVO votype = PfDataCache.getBillType(transtypepk);
            transtype = votype.getPk_billtypecode();
        }

        String nbcrcode = NbcrCodeTool.getNbcrCodeByTranstype(transtype);

        // 编码规则生成vo的编码
        BillCodeContext billCodeContext = getBillCodeContext(nbcrcode);
        if (billCodeContext == null) {
            throw new BusinessException("当前编码规则不存在，请到【编码规则定义-全局】节点检查是否存在" + nbcrcode);
        }

        if (billCodeContext.isPrecode()) {
            String pk_group = InvocationInfoProxy.getInstance().getGroupId();
            String code = getBillcodeManage().getPreBillCode_RequiresNew(nbcrcode, pk_group, pk_group);
            getMainVO(vo).setAttributeValue("billno", code);
        }

        return vo;
    }


    @Override
    public AggPjapplVO preAddAggPjapplVO(Map<String, Object> userJson) throws BusinessException {
        AggPjapplVO result = null;

        PJApplHVO mainvo = new PJApplHVO();
        // 设置默认值
        initDefaultData(mainvo);
        AggPjapplVO aggvo = new AggPjapplVO();
        aggvo.setParent(mainvo);
        result = aggvo;
        return preAddAggPjapplVO(result, userJson);
    }

    @Override
    public AggPjapplVO preEditAggPjapplVO(String pk) throws BusinessException {
        return dao.findByPk(AggPjapplVO.class, pk, false);
    }

    @Override
    public AggPjapplVO copyAggPjapplVO(String pk) throws BusinessException {

        AggPjapplVO vo = dao.findByPk(AggPjapplVO.class, pk, false);

        getMainVO(vo).setPrimaryKey(null);
        getMainVO(vo).setStatus(VOStatus.NEW);

        getMainVO(vo).setAttributeValue("srcbilltype", null);
        getMainVO(vo).setAttributeValue("srcbillid", null);

        getMainVO(vo).setAttributeValue("billno", null);
        getMainVO(vo).setAttributeValue("pjname", null);
        // 编码规则生成vo的编码
        String transtype = vo.getParentVO().getTranstype();
        String transtypepk = vo.getParentVO().getTranstypepk();
        if (transtype == null) {
            BilltypeVO votype = NCLocator.getInstance().lookup(IBilltypeService.class).getBilltypeByid(transtypepk);
            transtype = votype.getPk_billtypecode();
        }
        String nbcrcode = NbcrCodeTool.getNbcrCodeByTranstype(transtype);
        BillCodeContext billCodeContext = getBillCodeContext(nbcrcode);
        if (billCodeContext == null) {
            throw new BusinessException("当前编码规则不存在，请到【编码规则定义-全局】节点检查是否存在" + nbcrcode);
        }
        if (billCodeContext.isPrecode()) {
            String pk_group = InvocationInfoProxy.getInstance().getGroupId();
            String code = getBillcodeManage().getPreBillCode_RequiresNew(nbcrcode, pk_group, pk_group);
            getMainVO(vo).setAttributeValue("billno", code);
        }
        getMainVO(vo).setAttributeValue("approvestatus", BillStatusEnum.FREE.toIntValue());
        getMainVO(vo).setAttributeValue("billmaker", InvocationInfoProxy.getInstance().getUserId());
        getMainVO(vo).setAttributeValue("approver", null);
        getMainVO(vo).setAttributeValue("approvenote", null);
        getMainVO(vo).setAttributeValue("approvedate", null);
        // 设置审计信息为空
        getMainVO(vo).setAttributeValue("creator", null);
        getMainVO(vo).setAttributeValue("creationtime", null);
        getMainVO(vo).setAttributeValue("modifier", null);
        getMainVO(vo).setAttributeValue("modifiedtime", null);
        getMainVO(vo).setAttributeValue("maketime", new UFDateTime(InvocationInfoProxy.getInstance().getBizDateTime()));

        PjapplCVO[] pjapplCVOs = (PjapplCVO[]) vo.getChildren(PjapplCVO.class);
        if (pjapplCVOs != null && pjapplCVOs.length > 0) {
            Arrays.stream(pjapplCVOs).forEach(subvo -> {
                subvo.setPrimaryKey(null);
                subvo.setStatus(VOStatus.NEW);
                subvo.setAttributeValue("srcbilltype", null);
                subvo.setAttributeValue("srcbillid", null);
                subvo.setAttributeValue("", null);
                subvo.setAttributeValue("", null);
            });
        }
        PjapplBVO[] pjapplBVOs = (PjapplBVO[]) vo.getChildren(PjapplBVO.class);
        if (pjapplBVOs != null && pjapplBVOs.length > 0) {
            Arrays.stream(pjapplBVOs).forEach(subvo -> {
                subvo.setPrimaryKey(null);
                subvo.setStatus(VOStatus.NEW);
                subvo.setAttributeValue("srcbilltype", null);
                subvo.setAttributeValue("srcbillid", null);
                subvo.setAttributeValue("rowno", null);
                subvo.setAttributeValue("srcrowno", null);
            });
        }
        return vo;
    }

    @Override
    public AggPjapplVO[] saveAggPjapplVO(AggPjapplVO vo) throws BusinessException {
        String pk = getVOPrimaryKey(vo);
        setDefaultVal(vo);
//        new AcePjapplicationDataRule().process(new AggPjapplVO[]{vo});
    	// modify by wy at 适配930 2024年10月28日
        //新增修改走校验
        if (vo.getParentVO().getApprovestatus()==-1) {
            new AcePjapplicationDataRule().process(new AggPjapplVO[]{vo});
        }
        if (StringUtils.isEmpty(pk)) {
            //在导入时，需要给版本号增加默认值
            vo.getParentVO().setVersionno(new UFDouble(1.0));
            //导入时自动计算和自动生成的字段不要取导入文件中的填写内容
            //1:项目周期：根据文件中的起始日期和截止日期判断
            //2项目总经费：根据文件子表金额自动计算
            //3一级指标、二级指标：带出文件中对应指标名称关联的一级和二级
            //4联系电话：自动带出导入用户关联人员的联系电话
            //5最后修改人\最后修改时间\审批人\审批时间\审批意见：保持为空
            AggPjapplVO[] vos = dao.insert(vo);
            SJXMUtil.sjxmCommitHandlerAggvo(vos,"2","1", "I","");
            return vos; // 插入
        } else {
        	// modify by wy at 适配930 2024年10月28日
            //TODO zzp 校验项目与副项目循环调用
            if (!StringUtils.isEmpty(vo.getParentVO().getBelongpro())){
                this.checkParentPro(vo.getParentVO().getPk_pjappl(), vo.getParentVO().getBelongpro());
            }
            // 修订版本处理 luolch
            ICompareRule<AggPjapplVO> crule = new VersionProcessRule();
            AggPjapplVO var2 = dao.findByPk(AggPjapplVO.class, pk);
            crule.process(new AggPjapplVO[]{vo}, new AggPjapplVO[]{var2});
            AggPjapplVO[] updatevo = dao.update(vo);
            if(vo.getParentVO().getPjlibcategory().equals(3) || vo.getParentVO().getPjlibcategory().equals(4)){ // 准入-修订:3  监管-修订:4
                SJXMUtil.sjxmPjlibcategoryHandlerAggvo(var2, updatevo,"2","1","XD","");
            }else if (vo.getParentVO().getPjlibcategory().equals(1)){
                PJApplHVO hvo = var2.getParentVO();
                String applyyear = hvo.getApplyyear();
                SJXMUtil.sjxmCommitHandlerAggvo(updatevo,"2","1","U",applyyear);
                ISuperVO[] bvos = var2.getChildren(PjapplPVO.class);
                if(!ArrayUtils.isEmpty(bvos)){ // 修改后的
                    List<String> lists = new ArrayList<>();
                    for (ISuperVO bvo : bvos) {
                        if(bvo.getStatus() == 0){ // 删除
                            if(bvo.getAttributeValue("vbdef1") != null){
                                lists.add(bvo.getAttributeValue("vbdef1")+"");
                            }
                        }
                    }
                    if(!lists.isEmpty()){
                        ISjxmHVOService service = NCLocator.getInstance().lookup(ISjxmHVOService.class);
                        AggSjxmVO[] aggSjxmVOS = service.listAggSjxmVOByPk(lists.toArray(new String[lists.size()]));
                        if (!ArrayUtils.isEmpty(aggSjxmVOS)) {
                            for (AggSjxmVO aggvo : aggSjxmVOS) {
                                SjxmHVO sjvo = aggvo.getParentVO();
                                sjvo.setStatus(VOStatus.UPDATED);
                                ISuperVO[] superVOS = aggvo.getChildren(SjxmBVO.class);
                                if (!ArrayUtils.isEmpty(superVOS)) {
                                    for (ISuperVO supervo : superVOS) {
                                        Object ysyear = supervo.getAttributeValue("ysyear");
                                        if (applyyear.equals(ysyear+"")) {
                                            supervo.setStatus(VOStatus.UPDATED);
                                            supervo.setAttributeValue("oneprono","");
                                            supervo.setAttributeValue("oneproname","");
                                            supervo.setAttributeValue("twoprono","");
                                            supervo.setAttributeValue("twoproname","");
                                            supervo.setAttributeValue("threeprono","");
                                            supervo.setAttributeValue("threeproname","");
                                            supervo.setAttributeValue("budstate","2");
                                            supervo.setAttributeValue("fourstate","1");
                                            supervo.setAttributeValue("bdbilldate",null);
                                            supervo.setAttributeValue("bdef1","N");
                                        }
                                    }
                                }

                            }

                        }
                        service.saveAggSjxmVO(aggSjxmVOS);
                    }
                }
            }else{
                PJApplHVO hvo = var2.getParentVO();
                String applyyear = hvo.getApplyyear();
                SJXMUtil.sjxmCommitHandlerAggvo(updatevo,"2","2","U",applyyear);
            }
            return updatevo; // 更新
        }
    }

    /**
     * 校验：校验提示：项目与父项目存在循环调用，请重新选择父项目
     * @param primaryKey
     * @param parentPk
     */
    private void checkParentPro(String primaryKey, String parentPk) {
        List<String> parentList = new ArrayList();
        this.queryAllParentPk(parentPk, parentList, 0);
        if (StringUtils.isNotEmpty(primaryKey) && parentList.contains(primaryKey)) {
            ExceptionUtils.wrappBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("pmbase_0", "01014p00-0161"));
        }
    }

    /**
     * zzp项目与父项目递归调用：
     * @param parentPk  父项目pk
     * @param parentList 父项目列表
     * @param mark 计算是否查询父项超时
     */
    private void queryAllParentPk(String parentPk, List<String> parentList, int mark) {
        if (parentPk != null) {
            VOQuery<ProjectHeadVO> query = new VOQuery(ProjectHeadVO.class);
            ProjectHeadVO[] vos = query.query(new String[]{parentPk});
            if (nc.vo.pmpub.common.utils.ArrayUtils.isEmpty(vos)) {
                ExceptionUtils.wrappBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("pmbase_0", "01014p00-0162"));
            }

            ProjectHeadVO vo = vos[0];
            parentList.add(vo.getPrimaryKey());
            parentPk = vo.getPk_parentpro();
            if (StringUtils.isEmpty(parentPk)) {
                return;
            }

            ++mark;
            if (mark == 1000) {
                ExceptionUtils.wrappBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("pmbase_0", "01014p00-0163"));
            }

            this.queryAllParentPk(parentPk, parentList, mark);
        }
    }

    /**
     * 保存前处理编码规则
     *
     * @param vos
     */
    private void setBillCode(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isNotEmpty(vos)) {
            for (AggPjapplVO vo : vos) {
                String pk = getVOPrimaryKey(vo);
                if (StringUtils.isEmpty(pk)) {
                    String transtype = vo.getParentVO().getTranstype();
                    String transtypepk = vo.getParentVO().getTranstypepk();
                    if (transtype == null) {
                        BilltypeVO votype = NCLocator.getInstance().lookup(IBilltypeService.class).getBilltypeByid(transtypepk);
                        transtype = votype.getPk_billtypecode();
                    }
                    String nbcrcode = NbcrCodeTool.getNbcrCodeByTranstype(transtype);
                    BillCodeContext billCodeContext = getBillCodeContext(nbcrcode);
                    String pk_group = InvocationInfoProxy.getInstance().getGroupId();
                    if (billCodeContext != null && !billCodeContext.isPrecode()) {
                        if (getMainVO(vo).getAttributeValue("billno") == null) {
                            String code = getBillcodeManage().getBillCode_RequiresNew(nbcrcode, pk_group,
                                    pk_group, getMainVO(vo));
                            getMainVO(vo).setAttributeValue("billno", code);
                        }
                    } else {
                        String code = (String) getMainVO(vo).getAttributeValue("billno");
                        getBillcodeManage().commitPreBillCode(nbcrcode, pk_group, pk_group, code);
                    }
                }
            }
        }
    }

    /**
     * 保存前设置审计信息
     *
     * @param vos
     */
    private void setAuditInfo(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isNotEmpty(vos)) {
            UFDateTime now = new UFDateTime();
            for (AggPjapplVO vo : vos) {
                String pk = getVOPrimaryKey(vo);
                if (StringUtils.isEmpty(pk)) {
                    // 设置创建人创建时间
                    getMainVO(vo).setAttributeValue("creator", InvocationInfoProxy.getInstance().getUserId());
                    getMainVO(vo).setAttributeValue("creationtime", now);
                    getMainVO(vo).setAttributeValue("maketime", now);
                    getMainVO(vo).setAttributeValue("billmaker", InvocationInfoProxy.getInstance().getUserId()); // 制单人
                    getMainVO(vo).setAttributeValue("modifier", null);
                    getMainVO(vo).setAttributeValue("modifiedtime", null);
                } else {
                    // 设置修改人修改时间
                    getMainVO(vo).setAttributeValue("modifier", InvocationInfoProxy.getInstance().getUserId());
                    getMainVO(vo).setAttributeValue("modifiedtime", now);
                    getMainVO(vo).setAttributeValue("lastmaketime", now);
                }
            }
        }
    }

    /**
     * 保存前处理一些默认值
     *
     * @param vos
     */
    private void setDefaultVal(AggPjapplVO... vos) throws BusinessException {
        setBillCode(vos);
        setAuditInfo(vos);
        // 其他默认值处理
    }

    // 给单表（行编辑表）单独适配
    @Override
    public AggPjapplVO[] saveAggPjapplVO(AggPjapplVO[] vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return new AggPjapplVO[0];
        }
        setDefaultVal(vos); // 设置默认值
        List<String> pks = Arrays.stream(vos).filter(v -> getMainVO(v).getStatus() == VOStatus.DELETED)
                .map(v -> getMainVO(v).getPrimaryKey()).collect(Collectors.toList()); // 删除单据主键
        if (pks == null || pks.size() == 0) {
            return dao.save(vos, true);
        }
        AggPjapplVO[] deleteVOs = dao.listByPk(AggPjapplVO.class, pks.toArray(new String[0]));
        for (int i = 0; i < deleteVOs.length; i++) {
            SuperVO mainVO = getMainVO(deleteVOs[i]);
            // 删除单据时校验单据状态
            Integer approveStatus = (Integer) mainVO.getAttributeValue("approvestatus");
            if (approveStatus != null && !approveStatus.equals(-1)) {
                throw new BusinessException("第" + (i + 1) + "张单据处理失败：单据状态不正确，不能删除！");
            }
            // 删除单据时回退单据号
            String code = (String) mainVO.getAttributeValue("billno");
            if (StringUtils.isNotEmpty(code)) {
                String pk_group = InvocationInfoProxy.getInstance().getGroupId();
                String transtype = (String) mainVO.getAttributeValue("transtype");
                String transtypepk = (String) mainVO.getAttributeValue("transtypepk");
                if (transtype == null) {
                    BilltypeVO votype = NCLocator.getInstance().lookup(IBilltypeService.class).getBilltypeByid(transtypepk);
                    transtype = votype.getPk_billtypecode();
                }
                String nbcrcode = NbcrCodeTool.getNbcrCodeByTranstype(transtype);
                getBillcodeManage().returnBillCodeOnDelete(nbcrcode, pk_group, pk_group, code, deleteVOs[i]);
            }
        }
        return dao.save(vos, true);
    }

    @Override
    public AggPjapplVO[] deleteAggPjapplVOs(Map<String, String> tsMap) throws BusinessException {
        AggPjapplVO[] vos = dao.listByPk(AggPjapplVO.class, tsMap.keySet().toArray(new String[0]));
        validate(vos, tsMap);
        String pk_group = InvocationInfoProxy.getInstance().getGroupId();
        Arrays.stream(vos).forEach(vo -> {
            String code = (String) getMainVO(vo).getAttributeValue("billno");

            String transtype = (String) getMainVO(vo).getAttributeValue("transtype");
            String transtypepk = (String) getMainVO(vo).getAttributeValue("transtypepk");
            if (transtype == null) {
                try {
                    BilltypeVO votype = NCLocator.getInstance().lookup(IBilltypeService.class).getBilltypeByid(transtypepk);
                    transtype = votype.getPk_billtypecode();
                } catch (BusinessException e) {
                    ExceptionUtils.wrappBusinessException(e.getMessage(), e);
                }
            }
            String nbcrcode = NbcrCodeTool.getNbcrCodeByTranstype(transtype);
            try {
                getBillcodeManage().returnBillCodeOnDelete(nbcrcode, pk_group, pk_group, code, vo);
            } catch (BusinessException e) {
                ExceptionUtils.wrappBusinessException(e.getMessage(), e);
            }
        });
        // modify by wy at 适配930 2024年10月28日
        String[] apj = new String[vos.length];
        for (int i = 0; i < vos.length; i++) {
            apj[i] = vos[i].getPrimaryKey();
        }
        ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                .queryProjectBillVOsBypks(apj);
        if (pbvos.length > 0 ) {
            ExceptionUtils.wrappBusinessException("申请单已经生成项目档案，不允许直接删除申请单。若想删除申请单，请进行退库操作！");
        }
        SJXMUtil.sjxmUNCommitHandlerAggvo(vos, "2","2", "D","");
        dao.delete(vos, true);
        return vos;
    }

    // 校验 包括ts校验 已提交校验
    private void validate(AggPjapplVO[] vos, Map<String, String> tsMap) throws BusinessException {

        Boolean isPass = true;
        String error = ""; // 错误信息
        if (ArrayUtils.isEmpty(vos)) {
            isPass = false;
        }

        for (int i = 0; i < vos.length; i++) {
            SuperVO mainvo = vos[i].getParentVO();
            UFDateTime ts = (UFDateTime) mainvo.getAttributeValue("ts");
            if (!StringUtils.equals(tsMap.get(mainvo.getPrimaryKey()), ts.toString())) {
                isPass = false;
                break;
            }
            Integer approvestatus = (Integer) mainvo.getAttributeValue("approvestatus");
            if (approvestatus == null || approvestatus != BillStatusEnum.FREE.toIntValue()) {
                error += "第" + (i + 1) + "张单据处理失败：审批状态不正确，不能删除！\n";
            }
        }
        if (!isPass) {
            throw new BusinessException("您操作的数据已被他人修改或删除，请刷新后重试！");
        }
        if (!"".equals(error)) {
            throw new BusinessException(error);
        }
    }

    @Override
    public <T> T[] loadTreeData(Class<T> clazz, Map<String, Object> userJson) throws BusinessException {
        String condition = "dr = 0 ";
        return dao.listByCondition(clazz, condition, false);
    }

    @Override
    public String[] queryChildPksByParentId(Class childClazz, String parentId) throws BusinessException {
        String cond = " pk_pjappl = '" + parentId + "' ";
        SuperVO[] vos = (SuperVO[]) dao.listByCondition(childClazz, cond, false);
        if (vos == null || vos.length == 0) {
            return new String[0];
        }
        return Stream.of(vos).map(vo -> vo.getPrimaryKey()).toArray(String[]::new);
    }

    public SuperVO[] queryChildVOByPks(Class childClazz, String[] pks) throws BusinessException {
        return (SuperVO[]) dao.listByPk(childClazz, pks, false);
    }

    /**
     * 提交前校验: 检查单据状态
     *
     * @throws BusinessException
     */
    private void validateCommitAggPjapplVO(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return;
        }
        List<AggPjapplVO> list = Arrays.stream(vos).filter(item -> item.getParentVO() != null).filter(item -> {
            Integer status = (Integer) item.getParentVO().getAttributeValue("approvestatus");
            return status == null
                    || status != BillStatusEnum.FREE.toIntValue() && status != BillStatusEnum.NOPASS.toIntValue();
        }).map(item -> item).collect(Collectors.toList());
        if (list == null || list.size() == 0) {
            return;
        }
        String errors = "";
        for (AggPjapplVO vo : list) {
            errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]提交失败，失败原因：单据状态不正确，请检查。\n";
        }
        throw new BusinessException(errors);
    }

    /**
     * 收回前校验: 检查单据状态
     *
     * @throws BusinessException
     */
    private void validateUnCommitAggPjapplVO(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return;
        }
        //单据状态校验
        List<AggPjapplVO> list = Arrays.stream(vos).filter(item -> item.getParentVO() != null).filter(item -> {
            Integer status = (Integer) item.getParentVO().getAttributeValue("approvestatus");
            return status == null || status == BillStatusEnum.FREE.toIntValue();
        }).map(item -> item).collect(Collectors.toList());

        String errors = "";
        for (AggPjapplVO vo : list) {
            errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]收回失败，失败原因：单据状态不正确，请检查。\n";
        }
        //所属项目库类型校验，项目库不需要收回
        List<AggPjapplVO> validPjlibcategorylist = Arrays.stream(vos).filter(item -> item.getParentVO() != null).filter(item -> {
            Integer status = (Integer) item.getParentVO().getAttributeValue("pjlibcategory");
            return status == PjlibcategoryEnumerate.执行库.toIntValue();
//            return status == 1;
        }).map(item -> item).collect(Collectors.toList());
        if (validPjlibcategorylist == null || validPjlibcategorylist.size() == 0) {
            return;
        }
        for (AggPjapplVO vo : validPjlibcategorylist) {
            errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]收回失败，失败原因：单据已进入执行库，不允许收回。\n";
        }
//        throw new BusinessException(errors);
        // modify by wy at 适配930 2024年10月28日
        if (!errors.isEmpty()){
            throw new BusinessException(errors);
        }
    }

    @Override
    public Object commitAggPjapplVO(String actionName, Map<String, String> tsMap, Object assign)
            throws BusinessException {
        BillQuery<AggPjapplVO> billQuery = new BillQuery<AggPjapplVO>(AggPjapplVO.class);
        AggPjapplVO[] vos = billQuery.query(getAllPks(tsMap));
//        AggPjapplVO[] vos = dao.listByPk(AggPjapplVO.class, getAllPks(tsMap), false); local15
        validateTs(tsMap, vos);
        // 提交前校验及业务逻辑
        validateCommitAggPjapplVO(vos);
        Map<String, Object> res = this.execFlows(actionName, "PL01", assign, vos);
        // 提交后业务逻辑
//		BDCommonEventUtil bd = new BDCommonEventUtil("8335d483-15dc-4782-a7b6-00181cd7dac0");
//		bd.dispatchInsertAfterEvent(obj);
//		new AcePjapplicationCategoryDataRule().process(vos);
//        // modify 回写四级采购项目
//        SJXMUtil.sjxmCommitHandlerAggvo(vos,"2","2", "U","");
        return res;
    }

    @Override
    public Object batchCommitAggPjapplVO(String actionName, Map<String, String> tsMap) throws BusinessException {
        AggPjapplVO[] vos = dao.listByPk(AggPjapplVO.class, getAllPks(tsMap), false);
        validateTs(tsMap, vos);
        // 批量提交前校验及业务逻辑
        validateCommitAggPjapplVO(vos);
        Map<String, Object> res = this.execFlows(actionName, "PL01", vos);
        // 批量提交后业务逻辑
//		new AcePjapplicationCategoryDataRule().process(vos);
        return res;
    }

    @Override
    public Object uncommitAggPjapplVO(String actionName, Map<String, String> tsMap) throws BusinessException {
        AggPjapplVO[] vos = dao.listByPk(AggPjapplVO.class, getAllPks(tsMap), false);
        validateTs(tsMap, vos);
        // 收回前校验及业务逻辑
        validateUnCommitAggPjapplVO(vos);
        Map<String, Object> res = this.execFlows(actionName, "PL01", vos);
        // 收回后业务逻辑
//		new AcePjapplicationCategoryDataRule().process(vos);
        SJXMUtil.sjxmUNCommitHandlerAggvo(vos, "2", "1", "U","");
        return res;
    }

    @Override
    public Object batchUncommitAggPjapplVO(String actionName, Map<String, String> tsMap) throws BusinessException {
        AggPjapplVO[] vos = dao.listByPk(AggPjapplVO.class, getAllPks(tsMap), false);
        validateTs(tsMap, vos);
        // 批量收回前校验及业务逻辑
        validateUnCommitAggPjapplVO(vos);
        Map<String, Object> res = this.execFlows(actionName, "PL01", vos);
        // 批量收回后业务逻辑
//		new AcePjapplicationCategoryDataRule().process(vos);
        return res;
    }

    @Override
    public AggPjapplVO[] callbackSAVEBASE(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        return this.saveAggPjapplVO(vos);

    }

    @Override
    public AggPjapplVO[] callbackSAVE(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        // 同步单据状态和审批状态(只有提交时候需要手动设置审批状态。其余审批完后审批状态都已更新)
        Arrays.stream(vos).forEach(v -> {
            v.getParent().setAttributeValue("approvestatus", BillStatusEnum.COMMIT.toIntValue());
        });
        return this.saveAggPjapplVO(vos);

    }

    @Override
    public AggPjapplVO[] callbackUNSAVE(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        //更新项目库类别
        updatePjlCategory(vos);
        //收回需要多设置一下状态
        Arrays.stream(vos).forEach(v -> v.getParent().setStatus(VOStatus.UPDATED));
        return this.saveAggPjapplVO(vos);

    }

    @Override
    public AggPjapplVO[] callbackAPPROVE(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        //更新项目库类别
        updatePjlCategory(vos);
        //处理入库
        String[] apj = new String[vos.length];
        for (int i = 0; i < vos.length; i++) {
            apj[i] = vos[i].getPrimaryKey();
        }
        updateProject(apj,vos);
        // modify by at  wy at 审批通过回写四级采购项目
        this.approveUpdateFourProject(vos);

        return this.saveAggPjapplVO(vos);

    }

    @Override
    public AggPjapplVO[] callbackUNAPPROVE(AggPjapplVO... vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        //HOPG 2024年8月27日HPCLOUD-38489

        String errors = "";

        List<AggPjapplVO> validPjlibcategorylist = Arrays.stream(vos).filter(item -> item.getParentVO() != null).filter(item -> {
            Integer status = (Integer) item.getParentVO().getAttributeValue("pjlibcategory");
            return status == PjlibcategoryEnumerate.执行库.toIntValue();
        }).map(item -> item).collect(Collectors.toList());
        if (validPjlibcategorylist != null && validPjlibcategorylist.size() > 0) {

            for (AggPjapplVO vo : validPjlibcategorylist) {
                errors += "单据号：[" + vo.getParentVO().getAttributeValue("billno") + "]取消审核失败，失败原因：单据已进入执行库，不允许取消审核。\n";
            }
            if (!errors.isEmpty()){
                throw new BusinessException(errors);
            }
        }

        //更新项目库类别
        updatePjlCategory(vos);
        //更新项目库类别
        updatePjlCategory(vos);
        // modify by at  wy at 取消审批回写四级采购项目
        this.UnapproveUpdateFourProject(vos);
        return this.saveAggPjapplVO(vos);

    }
    // satart modify by wy at 2024年7月28日
    /**
         * 审批通过回写四级采购项目
     * @param vos
     * @throws BusinessException
     */
    protected void approveUpdateFourProject(AggPjapplVO [] vos) throws BusinessException{
        IUapbdFourProjectService service = NCLocator.getInstance().lookup(IUapbdFourProjectService.class);
    	try {
			service.approveUpdateFourProject(vos);
		} catch (BusinessException e) {
			throw new BusinessException("项目编制四级采购项目回写失败: " + e.getMessage());
		}
    }
    
    /**
         * 取消审批回写采购项目
     * @param vos
     * @throws BusinessException
     */
    protected void UnapproveUpdateFourProject(AggPjapplVO [] vos) throws BusinessException{
        IUapbdFourProjectService service = NCLocator.getInstance().lookup(IUapbdFourProjectService.class);
    	try {
			service.UnApproveUpdateFourProject(vos);
		} catch (Exception e) {
			throw new BusinessException("项目编制四级采购项目回写失败: " + e.getMessage());
		}
    	
    }
    
    // end modify by wy

    @Override
    public BillCodeContext getBillCodeContext(String coderuleid) throws BusinessException {
        return super.getBillCodeContext(coderuleid);
    }

    @Override
    public BillCodeContext getBillCodeContext(String coderuleid, String pkgroup, String pkorg)
            throws BusinessException {
        return super.getBillCodeContext(coderuleid, pkgroup, pkorg);
    }

    @Override
    public AggPjapplVO[] warehousing(AggPjapplVO[] clientFullVOs) throws BusinessException {
        if (clientFullVOs != null) {
            String[] apj = new String[clientFullVOs.length];
            for (int i = 0; i < clientFullVOs.length; i++) {
                apj[i] = clientFullVOs[i].getPrimaryKey();
            }
            List<AggPjapplVO> pjaayList = new ArrayList<AggPjapplVO>();
            for (int i = 0; i < clientFullVOs.length; i++) {
                AggPjapplVO aggPjapplVO = clientFullVOs[i];
                // 只有备选库的项目可以进行操作入项目库
                if (aggPjapplVO.getParentVO().getPjlibcategory() != PjlibcategoryEnumerate.储备库.toIntValue()) {
                    ExceptionUtils.wrappBusinessException("只有储备库的项目可以进行操作入项目库!");
                }
                // 项目状态:启用, 项目库类别:项目库
                aggPjapplVO.getParentVO().setPjlibcategory(PjlibcategoryEnumerate.执行库.toIntValue());
                aggPjapplVO.getParentVO().setPjstatus(PjstatusEnumerate.启用.toIntValue());
                pjaayList.add((AggPjapplVO) updateCategory(aggPjapplVO, new String[]{PJApplHVO.PJLIBCATEGORY, PJApplHVO.PJSTATUS}));
            }
            //更新项目节点数据
            updateProject(apj,clientFullVOs);

            return pjaayList.toArray(new AggPjapplVO[0]);
        }
        return new AggPjapplVO[0];
    }

    //更新/新增  项目节点数据
    private void updateProject(String[] apj,AggPjapplVO[] clientFullVOs) throws BusinessException {
        ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                .queryProjectBillVOsBypks(apj);

        IProject lookup = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProject.class);

        if (pbvos != null && pbvos.length > 0) {
            // 如果存在名称相同的项目，则将项目-项目组织的项目编码更新至项目申请中，其他字段按照以上规则同步
            ProjectBillVO[] projects = covertvotovo(clientFullVOs, pbvos);
            for (ProjectBillVO project : projects) {
                lookup.update(new ProjectBillVO[]{project});
            }
        } else {
            ProjectBillVO[] projects = covertvotovo(clientFullVOs, null);
            for (ProjectBillVO project : projects) {
                lookup.insert(new ProjectBillVO[]{project});
            }

        }
    }


    //更新项目库类别
    public AggPjapplVO[] updatePjlCategory(AggPjapplVO[] vos) throws BusinessException {
        UFBoolean HRPXM004 = SysInitQuery.getParaBoolean(vos[0].getParentVO().getPk_group(), "HRPXM004"); // 常规项目申请审批通过直接进入项目库
        UFBoolean HRPXM005 = SysInitQuery.getParaBoolean(vos[0].getParentVO().getPk_group(), "HRPXM005"); // 非常规项目申请审批通过直接进入项目库
        // 修改vos项目库的状态
        for (int i = 0; i < vos.length; i++) {
            if (vos[i].getParentVO().getApprovestatus() == 0) {// 审批不通过改为淘汰库
                vos[i].getParentVO().setPjlibcategory(5);
            } else if (vos[i].getParentVO().getApprovestatus() == 1) {// 审批通过
                if ("PL01-Cxx-PJ01".equals(vos[i].getParentVO().getTranstype())) {
                    if (HRPXM004.booleanValue()) {
                        vos[i].getParentVO().setPjlibcategory(4); //项目库
                        vos[i].getParentVO().setPjstatus(2); //项目状态:启用
                    } else {
                        vos[i].getParentVO().setPjlibcategory(3); //备选库
                    }
                } else {
                    if (HRPXM005.booleanValue()) {
                        vos[i].getParentVO().setPjlibcategory(4);
                        vos[i].getParentVO().setPjstatus(2); //项目状态:启用
                    } else {
                        vos[i].getParentVO().setPjlibcategory(3);
                    }
                }
            } else if (vos[i].getParentVO().getApprovestatus() == 3) { // 提交态
                vos[i].getParentVO().setPjlibcategory(2); // 审批库
                vos[i].getParentVO().setPjstatus(1); //项目状态:不启用
            } else if (vos[i].getParentVO().getApprovestatus() == -1) {
                vos[i].getParentVO().setPjlibcategory(1); // 草稿库
            }
        }
        return vos;
    }

    //把项目申请的vo转换为项目的vo  modify by wuqhua
    //此处跟入库操作共用了  要进行改造,项目申请的所属项目库状态 != 项目库 的时候 不进行转化项目vo的操作
    public ProjectBillVO[] covertvotovo(AggPjapplVO[] aggPjapplVOS, ProjectBillVO[] pbvos) throws BusinessException {
        if (aggPjapplVOS != null) {
            // 编码billno->project_code,名称pjname->project_name,主键:pk_pjappl,pk_project
            // 项目曾用名称pjusename->project_ot_name,项目类型pjtype->pk_eps,责任人headuser->pk_dutier,开始时间startingdate->plan_start_date,结束日期closingdate->plan_finish_date
//            ProjectBillVO[] pbvoarr = new ProjectBillVO[aggPjapplVOS.length];
            ArrayList<ProjectBillVO> result = new ArrayList<>();
            //字段转化关系 适配930 增加 "bperformance,bperformance"
            String[] fieldtofield = new String[]{"billno,project_code", "pjname,project_name",
                    "pjusename,project_ot_name", "pjtype,pk_eps", "headuser,pk_dutier", "startingdate,plan_start_date",
                    "closingdate,plan_finish_date", "pk_pjappl,pk_project", "pk_group,pk_group",
                    "belongpro,pk_parentpro", "officedept,pk_duty_dept_v", "governmentpurchase,govpurch", 
                    "addedassetallocation,assetallocation","applyyear,nyear","bperformance,bperformance",
                    "def1,def1"// modify by wy 2024年6月13日增加项目级次
            };

            for (int i = 0; i < aggPjapplVOS.length; i++) {
                AggPjapplVO aggPjapplVO = aggPjapplVOS[i];
                if (aggPjapplVO.getParentVO().getPjlibcategory() != 4){
                    continue;
                }
                ProjectBillVO projectBillVO = new ProjectBillVO();
//                projectBillVO.setParentVO(new ProjectHeadVO());
                // modify by wy at 2024年10月29日适配930 
                if(Objects.nonNull(pbvos)){
                    projectBillVO = (ProjectBillVO) pbvos[0].clone();
                    projectBillVO.getParentVO().setStatus(VOStatus.UPDATED);
                }else{
                    projectBillVO.setParentVO(new ProjectHeadVO());
                    projectBillVO.getParentVO().setStatus(VOStatus.NEW);

                }
                
                // 表头信息
                for (int j = 0; j < fieldtofield.length; j++) {
                    String[] fieldv = fieldtofield[j].split(",");
                    Object attributeValue = aggPjapplVO.getParent().getAttributeValue(fieldv[0]);
                    if (attributeValue != null) {
//                        projectBillVO.getParentVO().setAttributeValue(fieldv[1], attributeValue);
                        // modify by wy at 2024年10月29日适配930 
                        if (fieldv[0].equals("officedept"))
                        {
                            Collection<DeptVO> dept = dao.getBaseDAO().retrieveByClause(DeptVO.class, "pk_dept='" + attributeValue + "'");
                            projectBillVO.getParentVO().setAttributeValue(fieldv[1], dept.toArray(new DeptVO[0])[0].getPk_vid());
                            projectBillVO.getParentVO().setAttributeValue("pk_duty_dept", attributeValue);
                        }
                        else
                        {
                            projectBillVO.getParentVO().setAttributeValue(fieldv[1], attributeValue);
                        }

                    }
                }
                // HOPG 处理新增字段 2024年4月12日
                if(projectBillVO.getParentVO().getStatus()== VOStatus.NEW){
                    String pk_eps = aggPjapplVO.getParentVO().getPjtype();
                    if(StringUtils.isNotEmpty(pk_eps)){
                        EpsVO eps = (EpsVO) dao.getBaseDAO().retrieveByPK(EpsVO.class,pk_eps);
                        ProjectHeadVO head = projectBillVO.getParentVO();
                        head.setByearautoforward(eps.getByearautoforward());
                        head.setBoutlaycontrol(eps.getBoutlaycontrol());
                        //2024年05月29日  HOPG 应HOP预算群2024群里消息，冯老师要求，去掉这两个字段
//                        head.setGovpurch(eps.getBgovpur());
//                        head.setAssetallocation(eps.getBnewassets());
                    }
                }
                // 补齐其他信息
                projectBillVO.getParentVO().setPk_org(aggPjapplVO.getParentVO().getPk_org());
                projectBillVO.getParentVO().setPk_group(aggPjapplVO.getParentVO().getPk_group());
                projectBillVO.getParentVO().setPk_org_v(aggPjapplVO.getParentVO().getPk_org_v());
                projectBillVO.getParentVO().setFilesource(1);
                // 默认启用
//                projectBillVO.getParentVO().setEnablestate(EnableStateEnum.ENABLE.toIntValue());
                projectBillVO.getParentVO().setEnablestate(2);

                //如果是集团项目 则进入 项目-集团节点
                if (aggPjapplVO.getParentVO().getIsgroup().booleanValue()) {
                    projectBillVO.getParentVO().setPk_org(aggPjapplVO.getParentVO().getPk_group());
                }

                // 是否来源项目库：Y
                projectBillVO.getParentVO().setAttributeValue("isfromhrppl", UFBoolean.TRUE);

                // 子表信息处理
                ProjectBodyVO projectBodyVO = new ProjectBodyVO();
                // modify by wy at 适配930 2024年10月28日
                if(Objects.nonNull(pbvos)){
                    projectBodyVO = pbvos[0].getProjectBodyVO()[0];
                    projectBodyVO.setStatus(VOStatus.UPDATED);
                }
                projectBodyVO.setPk_org(aggPjapplVO.getParentVO().getPk_org());
                projectBodyVO.setPk_org_v(aggPjapplVO.getParentVO().getPk_org_v());
                projectBodyVO.setPk_parti_org(aggPjapplVO.getParentVO().getPk_org());
                projectBodyVO.setPk_parti_org_v(aggPjapplVO.getParentVO().getPk_org_v());
                projectBodyVO.setPk_group(aggPjapplVO.getParentVO().getPk_group());

                projectBillVO.setChildrenVO(new ProjectBodyVO[]{projectBodyVO});

                result.add(projectBillVO);
            }
            if (result.size() > 0) {
                return result.toArray(new ProjectBillVO[result.size()]);
            }else {
                return new ProjectBillVO[0];
            }
        }
        return new ProjectBillVO[0];
    }

    /**
     * 修改项目状态
     *
     * @param bill
     * @author luoliuchuan by
     */
    public AbstractBill updateCategory(AbstractBill bill, String[] fieldNames) {
        // 后续应该改为批量
        ISuperVO head = bill.getParent();
        try {
            dao.getBaseDAO().updateVO((SuperVO) head, fieldNames);
            ISuperVO sv = (ISuperVO) dao.getBaseDAO().retrieveByPK(head.getClass(), head.getPrimaryKey());
            bill.setParent(sv);
        } catch (DAOException e) {
            ExceptionUtils.wrappBusinessException("项目更新出错!");
        }
        return bill;
    }

    @Override
    public void updateCategory(String pk, int pjstatus) throws BusinessException {
        if (pjstatus > 0 && pjstatus <= 4) {
            PJApplHVO pjvo = new PJApplHVO();
            pjvo.setPk_pjappl(pk);
            pjvo.setPjstatus(pjstatus);
            dao.getBaseDAO().updateVO(pjvo, new String[]{"pjstatus"});
        } else {
            ExceptionUtils.wrappBusinessException("项目状态有误!!");
        }
    }

    @Override
    public AggPjapplVO warehousing(String pk) throws BusinessException {
        AggPjapplVO[] returnvo = warehousing(listAggPjapplVOByPk(pk));
        return returnvo == null ? null : returnvo[0];
    }


    @Override
    public AggPjapplVO unwarehousing(String pk) throws BusinessException {
        AggPjapplVO[] returnvo = unwarehousing(listAggPjapplVOByPk(pk));
        return returnvo == null ? null : returnvo[0];
    }

    public AggPjapplVO[] unwarehousing(AggPjapplVO[] clientFullVOs) throws BusinessException {
        // 根据pk取项目-组织,节点数据
        if (clientFullVOs != null) {
            List<AggPjapplVO> pjaayList = new ArrayList<AggPjapplVO>();
            String[] apj = new String[clientFullVOs.length];
            for (int i = 0; i < clientFullVOs.length; i++) {
                AggPjapplVO aggPjapplVO = clientFullVOs[i];
                // 只有项目库单据可取消,取消后为备选库
                if (aggPjapplVO.getParentVO().getPjlibcategory() != 4) {
                    ExceptionUtils.wrappBusinessException("只有项目库中的单据才可以取消入项目库操作,!");
                }
                aggPjapplVO.getParentVO().setPjlibcategory(3);
                aggPjapplVO.getParentVO().setPjstatus(1);
                nc.vo.util.AuditInfoUtil.updateData(aggPjapplVO.getParentVO());
                aggPjapplVO.getParentVO().setLastmaketime(aggPjapplVO.getParentVO().getModifiedtime());
                apj[i] = aggPjapplVO.getPrimaryKey();
                pjaayList.add((AggPjapplVO) updateCategory(aggPjapplVO, new String[]{"pjlibcategory", "pjstatus", "modifier", "modifiedtime", "lastmaketime"}));
            }
            ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                    .queryProjectBillVOsBypks(apj);
            if (pbvos.length > 0) {
                NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProject.class).delete(pbvos);
            }
            return pjaayList.toArray(new AggPjapplVO[0]);
            // 注册业务插件,处理数据引用问题
        }
        return new AggPjapplVO[0];
    }


    public AggPjapplVO[] closinitem(AggPjapplVO[] clientFullVOs) throws BusinessException {
//		项目结项，可以批量选择项目，点击后，经费不能再使用（项目申请状态为“结项”，项目档案状态为“停用”）。
        // 根据pk取项目-组织,节点数据
        //nc.vo.hrppl.hrppjplnum.PjstatusEnumerate
        if (clientFullVOs != null) {
            List<AggPjapplVO> pjaayList = new ArrayList<AggPjapplVO>();
            String[] apj = new String[clientFullVOs.length];
            for (int i = 0; i < clientFullVOs.length; i++) {
                AggPjapplVO aggPjapplVO = clientFullVOs[i];
                // 只有项目库单据可取消,取消后为备选库
                if (aggPjapplVO.getParentVO().getPjlibcategory() != 4) {
                    ExceptionUtils.wrappBusinessException("只有项目库中的单据才才可以做此操作,!");
                }
//				aggPjapplVO.getParentVO().setPjlibcategory(3);
                aggPjapplVO.getParentVO().setPjstatus(PjstatusEnumerate.结项.toIntValue());
                nc.vo.util.AuditInfoUtil.updateData(aggPjapplVO.getParentVO());
                aggPjapplVO.getParentVO().setLastmaketime(aggPjapplVO.getParentVO().getModifiedtime());
                apj[i] = aggPjapplVO.getPrimaryKey();
                pjaayList.add((AggPjapplVO) updateCategory(aggPjapplVO, new String[]{"pjlibcategory", "pjstatus", "modifier", "modifiedtime", "lastmaketime"}));
            }
            ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                    .queryProjectBillVOsBypks(apj);
            if (pbvos.length > 0 && pbvos[0].getParentVO().getEnablestate() == 3) {
                ExceptionUtils.wrappBusinessException("项目已停用，无法做此操作！");
            }
            if (pbvos.length > 0) {
                NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProject.class).disEnableProjects(new ProjectHeadVO[]{pbvos[0].getParentVO()});
            }
            return pjaayList.toArray(new AggPjapplVO[0]);
            // 注册业务插件,处理数据引用问题
        }
        return new AggPjapplVO[0];
    }


    public AggPjapplVO[] unClosinitem(AggPjapplVO[] clientFullVOs) throws BusinessException {
//		取消结项：状态反向更新，项目申请的项目状态为“启用”，项目档案状态为“启用”。
//		正反操作都要记录“修改人”和“最后修改时间”。
        // 根据pk取项目-组织,节点数据
        if (clientFullVOs != null) {
            List<AggPjapplVO> pjaayList = new ArrayList<AggPjapplVO>();
            String[] apj = new String[clientFullVOs.length];
            for (int i = 0; i < clientFullVOs.length; i++) {
                AggPjapplVO aggPjapplVO = clientFullVOs[i];
                // 只有项目库单据可取消,取消后为备选库
                if (aggPjapplVO.getParentVO().getPjlibcategory() != PjlibcategoryEnumerate.执行库.toIntValue()) {
                    ExceptionUtils.wrappBusinessException("只有执行库中的单据才才可以做此操作,!");
                }
//				aggPjapplVO.getParentVO().setPjlibcategory(3);
                aggPjapplVO.getParentVO().setPjstatus(PjstatusEnumerate.启用.toIntValue());
                apj[i] = aggPjapplVO.getPrimaryKey();
                pjaayList.add((AggPjapplVO) updateCategory(aggPjapplVO, new String[]{PJApplHVO.PJLIBCATEGORY, PJApplHVO.PJSTATUS}));
            }
            ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                    .queryProjectBillVOsBypks(apj);
            if (pbvos.length > 0) {
                NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProject.class).enableProjects(new ProjectHeadVO[]{pbvos[0].getParentVO()});
            }
            return pjaayList.toArray(new AggPjapplVO[0]);
            // 注册业务插件,处理数据引用问题
        }
        return new AggPjapplVO[0];
    }

    @Override
    public AggPjapplVO closinitem(String pk) throws BusinessException {
        AggPjapplVO[] returnvo = closinitem(listAggPjapplVOByPk(pk));
        return returnvo == null ? null : returnvo[0];
    }

    @Override
    public AggPjapplVO unClosinitem(String pk) throws BusinessException {
        AggPjapplVO[] returnvo = unClosinitem(listAggPjapplVOByPk(pk));
        return returnvo == null ? null : returnvo[0];
    }

    @Override
    public HashMap<String, Object> getBalanValue(String pk_project, String nyear, int srctype) throws BusinessException {
        HashMap map = new HashMap();
        List<LinkBugInfoVO> dataList = new ArrayList();
        //医院预算
        if (srctype == 1) {
            QryBudgetUtil qu = new QryBudgetUtil();
            dataList = qu.getBMBudgetData(pk_project);
            //科研预算

        }
        if (srctype == 2) {
            //专项预算

        }
        if (srctype == 3) {

        }
        map.put("dataList", dataList);
        return map;
    }

	@Override
	public void createHistory(String historyyear, ArrayList<String> pks) throws BusinessException {
        AggPjapplVO[] deletevos = dao.listByCondition(AggPjapplVO.class,"isnull(dr,0) = 99 and historyyear= '"+ historyyear + "' ");
        dao.delete(deletevos, true);

        List<AggPjapplVO> hisAggvos = new ArrayList<AggPjapplVO>();
        AggPjapplVO[] vos = listAggPjapplVOByPk(pks.toArray(new String[pks.size()]));

        for (int j = 0; j < vos.length; j++) {
            AggPjapplVO hisAggvo = (AggPjapplVO) vos[j].clone();
            PJApplHVO hvo = hisAggvo.getParentVO();

            hvo.setStatus(2);

            String billversionpk = hvo.getPrimaryKey();

            hvo.setPrimaryKey(null);

            hvo.setIslastversion(UFBoolean.FALSE);

            String endstr = "_" + hvo.getVersionno().setScale(1, 4).toString();
            hvo.setBillno(hvo.getBillno() + endstr);
            hvo.setCode(hvo.getCode() + endstr);
            hvo.setPjname(hvo.getPjname() + endstr);

            hvo.setModifier(AppContext.getInstance().getPkUser());

            hvo.setModifiedtime(AppContext.getInstance().getServerTime());

            hvo.setBillversionpk(billversionpk);

            hvo.setHistorypk(billversionpk);

            hvo.setHistoryyear(historyyear);

            SuperVO[] childVos = (SuperVO[]) hisAggvo.getChildren(PjapplBVO.class);
            if (childVos != null) {
                for (int i = 0; i < childVos.length; i++) {
                    childVos[i].setStatus(2);
                    childVos[i].setPrimaryKey(null);
                    childVos[i].setAttributeValue("pk_pjappl", null);
                }
            }

            SuperVO[] childcVos = (SuperVO[]) hisAggvo.getChildren(PjapplCVO.class);
            if (childcVos != null) {
                for (int i = 0; i < childcVos.length; i++) {
                    childcVos[i].setStatus(2);
                    childcVos[i].setPrimaryKey(null);
                    childcVos[i].setAttributeValue("pk_pjappl", null);
                }
            }

            hisAggvos.add(hisAggvo);

            UFDouble newversion = vos[j].getParentVO().getVersionno().add(0.1);
            vos[j].getParentVO().setVersionno(newversion);
        }

        if (hisAggvos.size() > 0) {
            InsertBPTemplate bp = new InsertBPTemplate(PjapplicationPluginPoint.INSERT);
            AggPjapplVO[] insResults = (AggPjapplVO[]) bp.insert(hisAggvos.toArray(new AggPjapplVO[0]));

            String[] insBillIds = new String[insResults.length];
            for (int i = 0; i < insResults.length; i++) {
                insBillIds[i] = insResults[i].getPrimaryKey();
            }

            InSqlManager insqlManager = new InSqlManager();
            String inSql = InSqlManager.getInSQLValue(insBillIds);
            String sql = "update hrppl_pjappl set dr = 99 where pk_pjappl in " + inSql;
            new BaseDAO().executeUpdate(sql);
        }

        dao.update(vos);
     }
     // begin modify by wy at 2025年1月13日
    @Override
    public AggPjapplVO unClosinitem(String pk, String bz) throws BusinessException {
        AggPjapplVO[] returnvo = unClosinitem(listAggPjapplVOByPk(pk), bz);
        return returnvo == null ? null : returnvo[0];
    }

    @Override
    public AggPjapplVO unwarehousing(String pk, String bz) throws BusinessException {
        AggPjapplVO[] returnvo = unwarehousing(listAggPjapplVOByPk(pk), bz);
        return returnvo == null ? null : returnvo[0];
    }

    @Override
    public AggPjapplVO closinitem(String pk, String bz) throws BusinessException {
        AggPjapplVO[] returnvo = closinitem(listAggPjapplVOByPk(pk), bz);
        return returnvo == null ? null : returnvo[0];
    }

    /**
     *
     * 原来代码不变，就增加备注
     * @param clientFullVOs
     * @param bz
     * @return
     * @throws BusinessException
     */
    public AggPjapplVO[] unClosinitem(AggPjapplVO[] clientFullVOs, String bz) throws BusinessException {
//		取消结项：状态反向更新，项目申请的项目状态为“启用”，项目档案状态为“启用”。
//		正反操作都要记录“修改人”和“最后修改时间”。
        // 根据pk取项目-组织,节点数据
        if (clientFullVOs != null) {
            List<AggPjapplVO> pjaayList = new ArrayList<AggPjapplVO>();
            String[] apj = new String[clientFullVOs.length];
            for (int i = 0; i < clientFullVOs.length; i++) {
                AggPjapplVO aggPjapplVO = clientFullVOs[i];
                // 只有项目库单据可取消,取消后为备选库
                if (aggPjapplVO.getParentVO().getPjlibcategory() != PjlibcategoryEnumerate.执行库.toIntValue()) {
                    ExceptionUtils.wrappBusinessException("只有执行库中的单据才才可以做此操作,!");
                }
                aggPjapplVO.getParentVO().setDef4(bz);//  增加备注 modify by wy at 2025年1月13日
                aggPjapplVO.getParentVO().setAttributeValue("def4", bz);//  增加备注 modify by wy at 2025年1月13日
//				aggPjapplVO.getParentVO().setPjlibcategory(3);
                aggPjapplVO.getParentVO().setPjstatus(PjstatusEnumerate.启用.toIntValue());
                apj[i] = aggPjapplVO.getPrimaryKey();
                pjaayList.add((AggPjapplVO) updateCategory(aggPjapplVO, new String[]{PJApplHVO.PJLIBCATEGORY, PJApplHVO.PJSTATUS, PJApplHVO.DEF4}));
            }
            ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                    .queryProjectBillVOsBypks(apj);
            if (pbvos.length > 0) {
                NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProject.class).enableProjects(new ProjectHeadVO[]{pbvos[0].getParentVO()});
            }
            return pjaayList.toArray(new AggPjapplVO[0]);
            // 注册业务插件,处理数据引用问题
        }
        return new AggPjapplVO[0];
    }

    /**
     * 原来代码不变，就增加备注
     * @param clientFullVOs
     * @param bz
     * @return
     * @throws BusinessException
     */
    public AggPjapplVO[] unwarehousing(AggPjapplVO[] clientFullVOs, String bz) throws BusinessException {
        // 根据pk取项目-组织,节点数据
        if (clientFullVOs != null) {
            List<AggPjapplVO> pjaayList = new ArrayList<AggPjapplVO>();
            String[] apj = new String[clientFullVOs.length];
            for (int i = 0; i < clientFullVOs.length; i++) {
                AggPjapplVO aggPjapplVO = clientFullVOs[i];
                // 只有项目库单据可取消,取消后为备选库
                if (aggPjapplVO.getParentVO().getPjlibcategory() != 4) {
                    ExceptionUtils.wrappBusinessException("只有项目库中的单据才可以取消入项目库操作,!");
                }
                aggPjapplVO.getParentVO().setDef4(bz);//  增加备注 modify by wy at 2025年1月13日
                aggPjapplVO.getParentVO().setAttributeValue("def4", bz);//  增加备注 modify by wy at 2025年1月13日
                aggPjapplVO.getParentVO().setPjlibcategory(3);
                aggPjapplVO.getParentVO().setPjstatus(1);
                nc.vo.util.AuditInfoUtil.updateData(aggPjapplVO.getParentVO());
                aggPjapplVO.getParentVO().setLastmaketime(aggPjapplVO.getParentVO().getModifiedtime());
                apj[i] = aggPjapplVO.getPrimaryKey();
                pjaayList.add((AggPjapplVO) updateCategory(aggPjapplVO, new String[]{"pjlibcategory", "pjstatus", "modifier", "modifiedtime", "lastmaketime","def4"}));
            }
            ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                    .queryProjectBillVOsBypks(apj);
            if (pbvos.length > 0) {
                NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProject.class).delete(pbvos);
            }
            return pjaayList.toArray(new AggPjapplVO[0]);
            // 注册业务插件,处理数据引用问题
        }
        return new AggPjapplVO[0];
    }

    /**
     * 项目结项 ---> 增加备注
     * @param clientFullVOs
     * @param bz
     * @return
     * @throws BusinessException
     */
    public AggPjapplVO[] closinitem(AggPjapplVO[] clientFullVOs, String bz) throws BusinessException {
//		项目结项，可以批量选择项目，点击后，经费不能再使用（项目申请状态为“结项”，项目档案状态为“停用”）。
        // 根据pk取项目-组织,节点数据
        //nc.vo.hrppl.hrppjplnum.PjstatusEnumerate
        if (clientFullVOs != null) {
            List<AggPjapplVO> pjaayList = new ArrayList<AggPjapplVO>();
            String[] apj = new String[clientFullVOs.length];
            for (int i = 0; i < clientFullVOs.length; i++) {
                AggPjapplVO aggPjapplVO = clientFullVOs[i];
                // 只有项目库单据可取消,取消后为备选库
                if (aggPjapplVO.getParentVO().getPjlibcategory() != 4) {
                    ExceptionUtils.wrappBusinessException("只有项目库中的单据才才可以做此操作,!");
                }
                aggPjapplVO.getParentVO().setDef4(bz);//  增加备注 modify by wy at 2025年1月13日
                aggPjapplVO.getParentVO().setAttributeValue("def4", bz);//  增加备注 modify by wy at 2025年1月13日
//				aggPjapplVO.getParentVO().setPjlibcategory(3);
                aggPjapplVO.getParentVO().setPjstatus(PjstatusEnumerate.结项.toIntValue());
                nc.vo.util.AuditInfoUtil.updateData(aggPjapplVO.getParentVO());
                aggPjapplVO.getParentVO().setLastmaketime(aggPjapplVO.getParentVO().getModifiedtime());
                apj[i] = aggPjapplVO.getPrimaryKey();
                pjaayList.add((AggPjapplVO) updateCategory(aggPjapplVO, new String[]{"pjlibcategory", "pjstatus", "modifier", "modifiedtime", "lastmaketime","def4"}));
            }
            ProjectBillVO[] pbvos = NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProjectQuery.class)
                    .queryProjectBillVOsBypks(apj);
            if (pbvos.length > 0 && pbvos[0].getParentVO().getEnablestate() == 3) {
                ExceptionUtils.wrappBusinessException("项目已停用，无法做此操作！");
            }
            if (pbvos.length > 0) {
                NCLocator.getInstance().lookup(nc.itf.pmpub.prv.IProject.class).disEnableProjects(new ProjectHeadVO[]{pbvos[0].getParentVO()});
            }
            return pjaayList.toArray(new AggPjapplVO[0]);
            // 注册业务插件,处理数据引用问题
        }
        return new AggPjapplVO[0];
    }
    // end modify by wy
}
